package dbTools.XML;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;

import projectsupporter.common.control.Path;

import dbTools.DBToolEngine;
import dbTools.tableInfo.field.Field;
import dbTools.tableInfo.field.fieldInfo.type.Type;
import dbTools.tableInfo.field.fieldInfo.type.types.TypeReference;
import dbTools.tableInfo.field.fields.NumberField;
import dbTools.tableInfo.info.TableInfo;

public class XMLService {

	public static List<String> createHibernateMapingFiles(Map<String,TableInfo> tableInfos,Path mainPath,boolean folderById)
	{
		List<String> mappingFiles=new ArrayList<String>();
		for(Map.Entry<String,TableInfo> entry : tableInfos.entrySet())
		{
			//mainFileName
			TableInfo tableInfo= entry.getValue();
			String key = tableInfo.getKey();
			
			Document doc = org.dom4j.DocumentHelper.createDocument();
			 doc.addDocType("hibernate-mapping",
					 "-//Hibernate/Hibernate Mapping DTD 3.0//EN",
					 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd");
			 
			 Element root = doc.addElement("hibernate-mapping");
			 
			 Element classElement=root.addElement("class");
			 
			 String mappingPath=mainPath.getPackagePath();
			 if(folderById)
			 {
				 mappingPath+="."+tableInfo.getTableId();
			 }
			 classElement.addAttribute("name", mappingPath+"."+key);
			 classElement.addAttribute("table", entry.getKey().toUpperCase());
			 classElement.addAttribute("lazy", "false");
			 
			 //Keys
			 setKey(tableInfo, classElement,key,mainPath,folderById);
			 
			 //propertys
			 setPropertys(tableInfo, classElement,mainPath,folderById);
			 
			 String path=mainPath.getAbsolutePath();
			 mappingPath=mainPath.getPackagePath().replace(".", "/");
			 if(folderById)
			 {
				 path+="\\"+tableInfo.getTableId();
				 mappingPath+="/"+tableInfo.getTableId();
			 }
			 CommonXmlCreator.createXML(doc, path,key+".hbm.xml");
			 
			 mappingFiles.add(mappingPath+"/"+key+".hbm.xml");
		}
		return mappingFiles;
	}

	private static void setKey(TableInfo tableInfo, Element classElement,String key,Path mainPath,boolean folderById) {
		if(tableInfo.getKeyFields().size()==1)
		 {
			Object[] keyValuePairs = tableInfo.getKeyFields().entrySet().toArray();
			Map.Entry<String, Field> entry = (Map.Entry<String, Field>)keyValuePairs[0];
			Field keyField=entry.getValue();
				 
			 Element id=classElement.addElement("id");
			 id.addAttribute("name", keyField.getFieldName());
			 id.addAttribute("type", keyField.getDataTypeString());
			 
			 Element column=id.addElement("column");
			 column.addAttribute("name", keyField.getFieldName().toUpperCase());
			//length
			setLength(keyField, column);
			
			//////////---------
			Element generator=id.addElement("generator");
			String generatorType = "assigned";
//			if(tableInfo.getKeyFields().size() == 1){
//				for(Map.Entry<String,Field> fieldEntry : tableInfo.getKeyFields().entrySet())
//				 {
//					 Field field=fieldEntry.getValue();
//					 if(field.getFieldInfo().getConStr().equals("[逻辑主键]")){
//						 generatorType = "native";
//					 }
//				 } 
//			}
			generator.addAttribute("class", generatorType);
			/////////-----------
		 }
		 else
		 {
			 Element compositeId=classElement.addElement("composite-id");
			 compositeId.addAttribute("name", "id");
			 String mappingPath=mainPath.getPackagePath();
			 if(folderById)
			 {
				 mappingPath+="."+tableInfo.getTableId();
			 }
			 compositeId.addAttribute("class", mappingPath+"."+key+"Id");
			 
			 for(Map.Entry<String,Field> fieldEntry : tableInfo.getKeyFields().entrySet())
			 {
				 Field field=fieldEntry.getValue();
				 TypeReference ref = DBToolEngine.getTypeReference_REFOnly(field);
				 if(ref==null)
				 {
					 Element keyProperty=compositeId.addElement("key-property");
					 keyProperty.addAttribute("name", fieldEntry.getKey());
					 keyProperty.addAttribute("type", field.getDataTypeString());
					 
					 Element column=keyProperty.addElement("column");
					 column.addAttribute("name", fieldEntry.getKey().toUpperCase());

					 //length
					 setLength(field, column);
				 }
				 else
				 {
					 TableInfo refTable=DBToolEngine.findTable(ref.getReferenceId());
					 String fileName = refTable.getTableId().substring(0,1).toUpperCase()+ refTable.getTableId().substring(1);
					 //Field refField=refTable.findField(ref.getReferenceField());
					 
					 Element keyProperty=compositeId.addElement("key-many-to-one");
					 keyProperty.addAttribute("name", fieldEntry.getKey());
					 mappingPath=mainPath.getPackagePath();
					 if(folderById)
					 {
						 mappingPath+="."+refTable.getTableId();
					 }
					 keyProperty.addAttribute("class", mappingPath + "."+fileName);
					 
					 Element column=keyProperty.addElement("column");
					 column.addAttribute("name", fieldEntry.getKey().toUpperCase());

					 //length
					 setLength(field, column);
				 }
			 } 
		 }
	}
	
	private static void setPropertys(TableInfo tableInfo, Element classElement,Path mainPath,boolean folderById) {
		for(Map.Entry<String,Field> fieldEntry : tableInfo.getAllFields().entrySet())
		 {
			 Field field=fieldEntry.getValue();
			 
			 if(field.isKey())
			 {
				 continue;
			 }
			 
			 TypeReference ref = DBToolEngine.getTypeReference_REFOnly(field);
			 if(ref==null)
			 {
				 Element property=classElement.addElement("property");
				 property.addAttribute("name", fieldEntry.getKey());
				 property.addAttribute("type", field.getDataTypeString());
				 
				 Element column=property.addElement("column");
				 column.addAttribute("name", fieldEntry.getKey().toUpperCase());
				 
				 //length
				 setLength(field, column);

				 //not null
				 if(field.isNotNull())
				 {
					 column.addAttribute("not-null", "true");
				 }
			 }
			 else
			 {
				 TableInfo refTable=DBToolEngine.findTable(ref.getReferenceId());
				 String fileName = refTable.getTableId().substring(0,1).toUpperCase()+ refTable.getTableId().substring(1);
				 Field refField=refTable.findField(ref.getReferenceField());
				 
				 Element property=classElement.addElement("many-to-one");
				 property.addAttribute("name", fieldEntry.getKey());
				 String mappingPath=mainPath.getPackagePath();
				 if(folderById)
				 {
					 mappingPath+="."+refTable.getTableId();
				 }
				 property.addAttribute("class", mappingPath+"."+fileName);
				 property.addAttribute("cascade", "none");
				 property.addAttribute("outer-join", "auto");
				 
//				 //view
//				 if(tableInfo.getTableId().startsWith("view")||tableInfo.getTableId().endsWith("view"))
//				 {
//					 property.addAttribute("update", "false");
//					 property.addAttribute("insert", "false"); 
//				 }
//				 else
//				 {
//					 property.addAttribute("update", "true");
//					 property.addAttribute("insert", "true");
//				 }
				 property.addAttribute("update", "false");
				 property.addAttribute("insert", "false"); 
				 
				 property.addAttribute("access", "property");
				 property.addAttribute("column", field.getFieldName().toUpperCase());
				 property.addAttribute("not-found", "ignore");
				 property.addAttribute("lazy", "false");
				 
			 }
		 }
	}

	private static void setLength(Field keyField, Element column) {
		if(keyField instanceof NumberField)
		 {
			 column.addAttribute("precision",String.valueOf(keyField.getLengh()));
			 if(((NumberField)keyField).getScale()!=0)
			 {
				 column.addAttribute("scale",String.valueOf(((NumberField)keyField).getScale()));
			 }
		 }
		 else
		 {
			 column.addAttribute("length",String.valueOf(keyField.getLengh()));
		 }
	}
}
